package com.simple.cloud.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.simple.cloud.core.utils.CryptUtil;
import com.simple.cloud.core.utils.ObjUtil;
import com.simple.cloud.domain.entity.SysRole;
import com.simple.cloud.domain.entity.SysUser;
import com.simple.cloud.domain.req.SysUserReq;
import com.simple.cloud.domain.resp.SysUserResp;
import com.simple.cloud.mapper.SysMenuMapper;
import com.simple.cloud.mapper.SysRoleMapper;
import com.simple.cloud.mapper.SysUserMapper;
import com.simple.cloud.service.SysUserService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

import static com.simple.cloud.core.consts.RedisCst.SYS_USER_KEY;


@CacheConfig(cacheNames = SYS_USER_KEY)
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    public SysUserResp getByUsername(String username) {
        QueryWrapper wrapper = QueryWrapper.create().where(SysUser::getUsername).eq(username);
        SysUserResp user = sysUserMapper.selectOneWithRelationsByQueryAs(wrapper, SysUserResp.class);
        if (ObjUtil.isNotNull(user) && ObjUtil.isNotNull(user.getRole())) {
            user.setMenus(user.getRole().getMenus());
            user.getRole().setMenus(null);
        }
//        if (ObjUtil.objIsNotNull(user)) {
//            SysRole role = sysRoleMapper.selectRoleByUserId(user.getId());
//            Set<SysMenu> menus = sysMenuMapper.selectMenusByUserId(user.getId());
//            user.setRole(role);
//            user.setMenus(menus);
//        }
        return user;
//        return sysUserMapper.selectUserByUsername(username);
    }


    @Override
    public SysUserResp getById(Long id) {
//        return sysUserMapper.selectOneWithRelationsByQueryAs(new QueryWrapper().where(SysUser::getId).eq(id), SysUserResp.class);
        return sysUserMapper.selectUserByUserId(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean resetPasswd(Long id, String password) {
        password = CryptUtil.hashPwd(password);
        SysUser entity = UpdateWrapper.of(SysUser.class).set(SysUser::getPassword, password).toEntity();
        QueryWrapper wrapper = QueryWrapper.create().where(SysUser::getId).eq(id);
        int i = sysUserMapper.updateByQuery(entity, wrapper);
        return i > 0;
    }


    @Override
    public Page<SysUserResp> getPage(SysUserReq req) {
        if (ObjUtil.isNull(req)) {
            req = new SysUserReq();
        }
        Page<SysUserResp> page = Page.of(req.getPageNum(), req.getPageSize());
        QueryWrapper wrapper = QueryWrapper.create()
                .where(SysUserReq::getId).eq(req.getId(), ObjUtil.isNotNull(req.getId()))
                .and(SysUserReq::getUsername).eq(req.getUsername(), ObjUtil.isNotNull(req.getUsername()))
                .and(SysUserReq::getEmail).eq(req.getEmail(), ObjUtil.isNotNull(req.getEmail()))
                .and(SysUserReq::getTelephone).eq(req.getTelephone(), ObjUtil.isNotNull(req.getTelephone()))
                .orderBy(req.toMybatisFlexOrders());
//        return sysUserMapper.paginateWithRelationsAs(page, wrapper, SysUserResp.class);
        return sysUserMapper.xmlPaginate("selectUserPage", page, wrapper);
    }

    @Override
    public List<SysUserResp> getList(SysUserReq req) {
        if (ObjUtil.isNull(req)) {
            req = new SysUserReq();
        }
        QueryWrapper wrapper = QueryWrapper.create()
                .where(SysUserReq::getId).eq(req.getId(), ObjUtil.isNotNull(req.getId()))
                .and(SysUserReq::getUsername).eq(req.getUsername(), ObjUtil.isNotNull(req.getUsername()))
                .and(SysUserReq::getEmail).eq(req.getEmail(), ObjUtil.isNotNull(req.getEmail()))
                .and(SysUserReq::getTelephone).eq(req.getTelephone(), ObjUtil.isNotNull(req.getTelephone()))
                .orderBy(req.toMybatisFlexOrders());
        return sysUserMapper.selectListWithRelationsByQueryAs(wrapper, SysUserResp.class);
    }

    @CacheEvict(cacheNames = {SYS_USER_KEY}, key = "'*'")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveAndEdit(SysUserReq req) {
        if (ObjUtil.isNull(req)) {
            return false;
        }
        if (ObjUtil.isNull(req.getRealName())) {
            req.setRealName(req.getUsername());
        }
        if (ObjUtil.isNotNull(req.getPassword())) {
            req.setPassword(CryptUtil.hashPwd(req.getPassword()));
        }
        boolean result = saveOrUpdate(req);
        if (!result) {
            return false;
        }
        Long roleId = req.getRoleId();
        if (ObjUtil.isNotNull(roleId)) {
            req.setRole(new SysRole().setId(roleId));
            sysUserMapper.deleteUserRoleRelationByUserIds(Collections.singletonList(req.getId()));
            sysUserMapper.saveUserRoleRelations(Collections.singletonList(req));
        }
//        SysUserResp loginUser = LoginHelper.getLoginUser();
//        if (Objects.equals(loginUser.getId(), req.getId())) {
//            SysUserResp newUser = getByUsername(req.getUsername());
//            LoginHelper.resetLoginUserInfo(loginUser, newUser);
//        }
        return true;
    }

    @CacheEvict(cacheNames = {SYS_USER_KEY}, key = "'*'")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteByIds(List<Long> ids) {
        if (ObjUtil.isNull(ids)) {
            return false;
        }
        sysUserMapper.deleteUserRoleRelationByUserIds(ids);
        return removeByIds(ids);
    }
}
